const std = @import("std");
const TerSeg = @import("terseg.zig");

pub const Self = @This();

seg: TerSeg,
map: std.ArrayList(Self),
lev: usize, // the level/depth of the current terMap node in the tree
num: usize, // the number of children of the current terMap node in the tree

// init always create a TerMap with seg and empty map list.
pub fn init(allocator: std.mem.Allocator, seg: TerSeg) Self {
    return Self{
        .seg = seg,
        .map = std.ArrayList(Self).init(allocator),
        .lev = 0,
        .num = 0,
    };
}

pub fn deinit(self: *Self) void {
    // Recursively deinit all map
    for (self.map.items) |*child| {
        child.deinit();
    }
    self.map.deinit();
}

pub fn addChild(self: *Self, child: Self) !void {
    try self.map.append(child);
}

pub fn len(self: Self) usize {
    var count: usize = 1;
    for (self.map.items) |child| {
        count += child.len();
    }
    return count;
}

pub fn print(self: Self, current_level: usize, max_level: usize) void {
    // Indentation
    for (0..current_level) |_| {
        std.debug.print("  ", .{});
    }
    self.seg.print("\n");
    if (current_level < max_level) {
        for (self.map.items) |child| {
            child.print(current_level + 1, max_level);
        }
    } else if (self.map.items.len > 0) {
        // Truncated children
        for (0..current_level + 1) |_| {
            std.debug.print("  ", .{});
        }
        std.debug.print("... {d} segs ...\n", .{self.map.items.len});
        // Print first and last child segs for context
        if (self.map.items.len > 1) {
            for (0..current_level + 1) |_| {
                std.debug.print("  ", .{});
            }
            self.map.items[0].seg.print("\n");
            for (0..current_level + 1) |_| {
                std.debug.print("  ", .{});
            }
            self.map.items[self.map.items.len - 1].seg.print("\n");
        } else {
            for (0..current_level + 1) |_| {
                std.debug.print("  ", .{});
            }
            self.map.items[0].seg.print("\n");
        }
    }
}

test "TerMap - basic operations" {
    const allocator = std.testing.allocator;

    // Create root node
    var root = Self.init(allocator, TerSeg.init(0b1111, 0b1010));
    defer root.deinit();

    // Add some map
    try root.addChild(Self.init(allocator, TerSeg.init(0b1100, 0b1100)));
    try root.addChild(Self.init(allocator, TerSeg.init(0b0011, 0b0011)));

    // Add a child to the first child
    try root.map.items[0].addChild(Self.init(allocator, TerSeg.init(0b1000, 0b1000)));

    // Test length
    try std.testing.expectEqual(@as(usize, 4), root.len());

    // Test printing
    std.debug.print("\nTerMap tree structure:\n", .{});
    root.print(0, 2);
}
